import 'package:dss_base/dss_base.dart';
import 'package:dss_base/net/base_entity.dart';
import 'package:dss_base/net/http_util.dart';
import 'package:dss_base/utils/log_util.dart';
import 'package:dss_base/widgets/base/state_holder.dart';
import 'package:flutter/cupertino.dart';

class BaseViewModel extends ChangeNotifier {
  final Map<ChangeNotifier, List<VoidCallback>> _notifierMap = {};

  void addSafeListener(ChangeNotifier notifier, VoidCallback listener){
    final list = _notifierMap.putIfAbsent(notifier, () => []);
    list.add(listener);
    notifier.addListener(listener);
  }

  void removeSafeListener(ChangeNotifier notifier){
    final list = _notifierMap[notifier];
    if (list != null) {
      for (var f in list) {
        notifier.removeListener(f);
      }
      _notifierMap.remove(notifier);
    }
  }

  void removeAllListener({bool isDispose = false}){
    for (var entry in _notifierMap.entries) {
      final notifier = entry.key;
      final listeners = entry.value;
      for (var f in listeners) {
        notifier.removeListener(f);
        if(isDispose){
          notifier.dispose();
        }
      }
    }
    _notifierMap.clear();
  }

  ValueNotifier<LoadingDialogState> dialogState = ValueNotifier(
    LoadingDialogState.init,
  );

  /// 加载对话框 - 显示
  void showLoadingDialog() {
    dialogState.value = LoadingDialogState.show;
  }

  /// 加载对话框 - 隐藏
  void hideLoadingDialog() {
    dialogState.value = LoadingDialogState.hide;
  }

  void setStateChanged() {
    notifyListeners();
  }

  /// 省事的加载逻辑
  void request<T>({
    bool isShowLoadingDialog = true,
    required Future<BaseEntity> request,
    required ApiConvert<T>? onConvert,
    required ApiSuccessCallback<T> onSuccess,
    ApiFailureCallback? onFailure,
  }) {
    if (isShowLoadingDialog) {
      showLoadingDialog();
    }
    HttpUtil.instance.request<T>(
      request: request,
      onConvert: onConvert,
      onSuccess: (entity, data) {
        if (isShowLoadingDialog) hideLoadingDialog();
        onSuccess.call(entity, data);
      },
      onFailure: (code, msg) {
        if (isShowLoadingDialog) hideLoadingDialog();
        if(onFailure == null){
          Toast.show(msg);
        }else{
          onFailure.call(code, msg);
        }
      },
    );
  }
}
